package com.party.mobile.biz.file;

import com.party.api.dto.wechat.requst.XcxQrCodeRequest;
import com.party.api.service.wechat.IWechatService;
import com.party.common.constant.Constant;
import com.party.common.utils.QRCodeUtil;
import com.party.core.model.file.FileEntity;
import com.party.core.service.cos.CosBizService;
import com.party.core.service.file.IFileEntityService;
import com.party.file.cos.dto.SearchResult;
import com.party.file.cos.dto.UploadResult;
import com.party.file.cos.meta.InsertOnly;
import com.party.mobile.biz.wechat.WechatBizService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

@Service
public class FileBizService {

    @Value("#{party['mic.url']}")
    private String micUrl;

    @Value("#{party['userfiles.basedir']}")
    private String baseDir;

    // 上传到万象优图路径
    @Value("#{party['upload.ci.path']}")
    private String uploadCIPath;

    @Autowired
    private IFileEntityService fileEntityService;

    @Autowired
    private WechatBizService wechatBizService;

    @Autowired
    private CosBizService cosBizService;

    @Autowired
    private IWechatService wechatService;

    Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 插入数据库
     *
     * @param file
     * @param path
     * @param targetId
     */
    public void insertFileEntity(File file, String path, String targetId) {
        FileEntity fileEntity = new FileEntity();
        fileEntity.setExtension(".jpg");
        fileEntity.setFileName(file.getName());
        fileEntity.setMimetype("image/jpeg");
        fileEntity.setPath(path);
        fileEntity.setSize(file.length());
        fileEntity.setOptionId(targetId);
        fileEntityService.insert(fileEntity);
    }

    /**
     * 生成二维码
     *
     * @param content        内容
     * @param path           路径
     * @param fileName       文件名
     * @param imgPath
     * @param isCastShortUrl 是否需要转短连接
     * @return
     */
    public File saveFile(String content, String path, String fileName, String imgPath, boolean isCastShortUrl, boolean isAppendMic, String publisher) {
        try {
            String basePath = baseDir + path;
            File dir = new File(basePath);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            String realPath = basePath + fileName;
            File file = new File(realPath);
            if (file.exists()) {
                file.delete();
            }
            if (!file.exists()) {
                file.createNewFile();

                if (isAppendMic) {
                    content = micUrl + content;
                }
                if (isCastShortUrl) {
                    content = getShortUrl(content, publisher);
                }
                logger.info("二维码连接：{}", content);

                OutputStream output = new FileOutputStream(realPath);

                String logoPath = null;
                if (StringUtils.isNotEmpty(imgPath)) {
                    logoPath = download(imgPath, realPath);
                    QRCodeUtil.encode(content, logoPath, output, true);
                } else {
                    QRCodeUtil.encode(content, output);
                }

                output.close();
            }
            return file;
        } catch (Exception e) {
            logger.error("生成二维码异常——二维码路径:" + baseDir + path + fileName, e);
        }
        return null;
    }

    /**
     * 下载网络图片到本地
     *
     * @param imgPath
     * @param realPath
     * @return
     */
    private String download(String imgPath, String realPath) {
        try {
            URL imgUrl = new URL(imgPath);
            HttpURLConnection connection = (HttpURLConnection) imgUrl.openConnection();
            connection.setDoInput(true);
            connection.connect();
            InputStream is = connection.getInputStream();
            byte[] data = readInputStream(is);

            String newPath = realPath.substring(0, realPath.lastIndexOf(".") - 1);
            newPath = newPath + "-1" + realPath.substring(realPath.lastIndexOf("."), realPath.length());
            File file = new File(newPath);
            if (!file.exists()) {
                file.createNewFile();
                FileOutputStream outputStream = new FileOutputStream(file);
                outputStream.write(data);
                outputStream.close();
            }
            return newPath;
        } catch (Exception e) {
            logger.error("下载网络图片到本地异常", e);
        }
        return null;
    }

    /**
     * 读取流
     *
     * @param is
     * @return
     * @throws IOException
     */
    private byte[] readInputStream(InputStream is) throws IOException {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] data = new byte[1024];
        int len = 0;
        while ((len = is.read(data)) != -1) {
            outStream.write(data, 0, len);
        }
        is.close();
        return outStream.toByteArray();
    }

    /**
     * 获取二维码路径（不带logo，不转短连接）
     *
     * @param targetId 文件名
     * @param path     文件路径
     * @param content  文件内容
     * @return 二维码路径
     */
    public String getFileEntity(String targetId, String path, String content) {
        String fileName = targetId + ".jpg";

        saveFile(content, path, fileName, null, false, true, null);

        return path + fileName;
    }

    /**
     * 获取二维码路径（不带logo）
     *
     * @param targetId       文件名
     * @param path           文件路径
     * @param content        文件内容
     * @param isCastShortUrl 是否需要转短连接
     * @return 二维码路径
     */
    public String getFileEntity(String targetId, String path, String content, boolean isCastShortUrl) {
        String fileName = targetId + ".jpg";

        saveFile(content, path, fileName, null, isCastShortUrl, true, null);

        return path + fileName;
    }

    /**
     * 获取二维码路径（带logo）
     *
     * @param targetId       文件名
     * @param path           文件路径
     * @param content        文件内容
     * @param imgPath        logo路径
     * @param isCastShortUrl 是否需要转短连接
     * @return 二维码路径
     */
    public String getFileEntity(String targetId, String path, String content, String imgPath, boolean isCastShortUrl) {
        String fileName = targetId + ".jpg";

        saveFile(content, path, fileName, imgPath, isCastShortUrl, true, null);

        return path + fileName;
    }

    /**
     * 获取短连接
     *
     * @param content
     * @return
     */
    public String getShortUrl(String content, String publisher) {
        if ((content.indexOf("http://") != -1 || content.indexOf("https://") != -1)) {
            String shortUrl = wechatBizService.longToShort2(content, publisher);
            if (StringUtils.isNotEmpty(shortUrl)) {
                return shortUrl;
            } else {
                shortUrl = wechatBizService.longToShort2(content, null);
                if (StringUtils.isNotEmpty(shortUrl)) {
                    return shortUrl;
                }
            }
        }
        return content;
    }

    /**
     * 上传二维码到万象优图(用作初始化时)
     *
     * @param cloudFileName 云文件名
     * @param cloudFilePath 云目录
     * @param content       内容
     * @param publisher     业务发布者
     * @param isAppendMic   是否追加微网站域名
     * @return
     */
    public String uploadCloudOut(String cloudFileName, String cloudFilePath, String content, String publisher, boolean isAppendMic) {
        return uploadCloudInner(cloudFileName, cloudFilePath, cloudFilePath, cloudFileName, content, publisher, isAppendMic);
    }

    /**
     * 上传二维码到万象优图
     *
     * @param cloudFileName 云文件名
     * @param cloudFilePath 云目录
     * @param content       内容
     * @return
     */
    public String uploadCloudOut(String cloudFileName, String cloudFilePath, String content, String publisher) {
        return uploadCloudInner(cloudFileName, cloudFilePath, cloudFilePath, cloudFileName, content, publisher, true);
    }

    /**
     * 获取二维码路径（不带logo）
     *
     * @param cloudFileName 云文件名
     * @param cloudFilePath 云文件路径
     * @param localFilePath 本地文件路径
     * @param content       文件内容
     * @return 二维码路径
     */
    private String uploadCloudInner(String cloudFileName, String cloudFilePath, String localFilePath, String localFileName, String content, String publisher, boolean isAppendMic) {
        cloudFileName = cloudFileName + ".jpg";
        cloudFilePath = "/" + cloudFilePath;
        try {
            String accessUrl = cosBizService.statFile(cloudFilePath + cloudFileName);
            if (StringUtils.isNotEmpty(accessUrl)) {
                return cosBizService.getPreviewPicUrl(accessUrl);
            } else {
                SearchResult newSearchResult = cosBizService.statFolder(cloudFilePath); // 检查目录是否存在
                Boolean result; // 目录操作结果
                if (newSearchResult.getCode() == 0 && newSearchResult.getMessage().equals(Constant.WECHAT_SUCCESS)) {
                    result = true; // 目录存在，则不用去创建目录
                } else {
                    result = cosBizService.createFolder(cloudFilePath); // 创建目录结果
                }

                if (result) { // 上传文件
                    InputStream inputStream = createQrCode(content, true, publisher, isAppendMic);
                    if (inputStream != null) {
                        byte[] bytes = readInputStream(inputStream);
                        ByteArrayInputStream input = new ByteArrayInputStream(bytes);
                        UploadResult upload = cosBizService.uploadFile(input, cloudFilePath + cloudFileName, InsertOnly.NO_OVER_WRITE);
                        return cosBizService.getPreviewPicUrl(upload.getAccessUrl());
                    }
                }
            }
        } catch (Exception e) {
            logger.error("上传二维码到万象优图异常：cloudFilePath——" + cloudFilePath + "；cloudFileName——" + cloudFileName, e);
        }
        return null;
    }

    public String getUploadCIPath(String memberId, String folderName) {
        String path = String.format(uploadCIPath, memberId, folderName);
        return path;
    }

    private InputStream createQrCode(String content, boolean isCastShortUrl, String publisher, boolean isAppendMic) {
        try {
            if (isAppendMic) {
                content = micUrl + content;
            }
            if (isCastShortUrl) {
                content = getShortUrl(content, publisher);
            }
            logger.info("二维码连接：{}", content);

            //BufferedImage 转 InputStream
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ImageOutputStream imageOutput = ImageIO.createImageOutputStream(byteArrayOutputStream);
            QRCodeUtil.encode(content, imageOutput);
            InputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
            return inputStream;
        } catch (Exception e) {
            logger.error("生成二维码异常", e);
        }
        return null;
    }
    /**
     * 上传到二维码到万象优图
     *
     * @param cloudFileName 云文件名
     * @param cloudFilePath 云目录
     * @param qrCodeRequest 生成二维码参数
     * @return
     */
    public String uploadCloudOutXcs(String cloudFileName, String cloudFilePath,
                                 XcxQrCodeRequest qrCodeRequest, String accessToken, Integer insertOnley) {
        return this.uploadCloudInnerXcx(cloudFileName, cloudFilePath, insertOnley, qrCodeRequest, accessToken);
    }

    /**
     * 获取二维码路径（不带logo）
     *
     * @param cloudFileName 云文件名
     * @param cloudFilePath 云文件路径
     * @param insertOnly    是否覆盖
     * @param qrCodeRequest 生成小程序二维码请求参数
     * @return 二维码路径
     */
    private String uploadCloudInnerXcx(String cloudFileName, String cloudFilePath, Integer insertOnly,
                                       XcxQrCodeRequest qrCodeRequest, String accessToken) {
        cloudFileName = cloudFileName + ".jpg";
        cloudFilePath = "/" + cloudFilePath;
        try {
            // 目录操作结果
            Boolean result = false;
            // 检查文件是否存在
            String accessUrl = cosBizService.statFile(cloudFilePath + cloudFileName);
            if (StringUtils.isNotEmpty(accessUrl)) {
                // 不覆盖
                if (1 == insertOnly) {
                    return cosBizService.getPreviewPicUrl(accessUrl);
                    // 删除覆盖
                } else if (0 == insertOnly) {
                    result = true;
                }
            } else {
                // 检查目录是否存在
                SearchResult newSearchResult = cosBizService.statFolder(cloudFilePath);
                if (newSearchResult.getCode() == 0 && newSearchResult.getMessage().equals(Constant.WECHAT_SUCCESS)) {
                    // 目录存在，则不用去创建目录
                    result = true;
                } else {
                    // 创建目录结果
                    result = cosBizService.createFolder(cloudFilePath);
                }
            }
            if (result) {
                // 上传文件
                InputStream inputStream = wechatService.createMiniProgramQrCode(qrCodeRequest, accessToken);
                if (inputStream != null) {
                    byte[] bytes = readInputStream(inputStream);
                    String str = new String(bytes, "UTF-8");
                    if (str.indexOf("errcode") != -1) {
                        throw new Exception(str);
                    }
                    ByteArrayInputStream input = new ByteArrayInputStream(bytes);
                    UploadResult upload = cosBizService.uploadFile(input, cloudFilePath + cloudFileName, InsertOnly.NO_OVER_WRITE);
                    return cosBizService.getPreviewPicUrl(upload.getAccessUrl());
                }
            }
        } catch (Exception e) {
            logger.error("上传二维码到万象优图异常：cloudFilePath——"
                    + cloudFilePath + "；cloudFileName——" + cloudFileName, e);
        }
        return null;
    }
}
